<template>
  <div class="gyk-common-dialog">
    <el-dialog :closeOnClickModal="false" :title="title" v-model="editDialogVisible" :width="width"
      :before-close="handleClose">
      <div class="gyk-common-dialog-container" v-loading="editDialogLoading">
        <el-form :model="editForm" :rules="formRules" ref="ruleFormRef" label-width="180px">
          <el-row class="assign-container">
            <el-col v-for="(item, index) in showFormInfo" :key="item.prop" :span="item.span" class="line-after">
              <el-form-item :label="item.label" :prop="item.prop" style="text-align: center !important;">
                <!-- 字典选择框 -->
                <el-select clearable :multiple="item.multiple" filterable v-if="item.type == 'select' && item.dictType"
                  v-model="editForm[item.prop]">
                  <el-option :key="option.dictValue" v-for="(option, index) in item.options" :label="option.dictLabel"
                    :value="option.dictValue">
                  </el-option>
                </el-select>

                <!-- 普通的选择框 -->
                <el-select clearable filterable :multiple="item.multiple"
                  v-else-if="item.type == 'select' && !item.dictType" v-model="editForm[item.prop]">
                  <el-option :key="option[item.optionProps.value]" v-for="(option, index) in item.options"
                    :label="option[item.optionProps.label]" :value="option[item.optionProps.value]">
                  </el-option>
                </el-select>

                <!-- 树形选择框 -->
                <el-tree-select v-else-if="item.type == 'selectTree'" :multiple="item.multiple"
                  v-model="editForm[item.prop]" :props="item.optionProps" :data="item.options" filterable />


                <!-- 日期类型表单 -->
                <el-date-picker class="datePicker" v-else-if="item.type == 'date'" format="yyyy-MM-dd"
                  value-format="yyyy-MM-dd" clearable v-model="editForm[item.prop]" placeholder="请选择日期">
                </el-date-picker>

                <!-- 文本域 -->
                <el-input v-else-if="item.type === 'textarea'" :rows="item.rows" type="textarea" resize="none"
                  show-word-limit placeholder="请输入" v-model="editForm[item.prop]">
                </el-input>

                <!-- 菜单权限 -->
                <div v-else-if="item.type === 'menuPermission'" class="gyk-menu-permission-box">
                  <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
                  <el-checkbox v-model="menuNodeAll"
                    @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
                  <el-checkbox v-model="editForm.menuCheckStrictly"
                    @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>

                  <!-- 菜单检索框 -->
                  <el-input style="border: 1px solid #ccc;" v-model="menuFilterText" placeholder="输入搜索条件" />

                  <el-tree class="tree-border" :data="menuOptions" show-checkbox ref="menuRef" node-key="id"
                    :filter-node-method="handleMenuFilter" :check-strictly="!editForm.menuCheckStrictly"
                    empty-text="加载中，请稍候" :props="defaultProps"></el-tree>
                </div>

                <!-- 密码输入框 -->
                <el-input v-else-if="item.type === 'password'" v-model="editForm[item.prop]" type="password"
                  :placeholder="item.placeholder"></el-input>

                <!-- 普通输入框 -->
                <el-input v-else v-model="editForm[item.prop]" type="input" :placeholder="item.placeholder"></el-input>
              </el-form-item>

            </el-col>
          </el-row>
        </el-form>
      </div>
      <div slot="footer" class="dialog-footer footer-wrapper">
        <el-button type="primary" :disabled="loading" @click="submitEditForm">{{ submitBtnText }}</el-button>
        <el-button @click="handleClose">关闭</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, reactive, getCurrentInstance, watch, nextTick } from 'vue'
import type { FormInstance, FormRules, ElTree } from 'element-plus'
import { FormInfo } from '@/types'

const app = getCurrentInstance()
// 接收参数
const defProps = withDefaults(defineProps<{
  // 标题
  title: string
  // 是否展示
  visible: boolean
  // 编辑表单
  editForm: any,
  // 表单信息
  formInfo: FormInfo[],
  // 提交按钮的文本
  submitBtnText: string,
  // 宽度
  width: string,
  // 高度
  dialogHeight: string,
  // 是否正在加载
  loading: boolean,
  // 菜单选项
  menuOptions: any[],
  // 部门选项
  deptOptions: any[],
  // 默认选中的菜单选项
  checkedMenuOptions: any[],
  // 操作
  operation: string,
}>(), {
  title: '标题',
  visible: false,
  editForm: () => { return {} },
  formInfo: () => [],
  submitBtnText: '确定',
  width: '70%',
  dialogHeight: '500px',
  loading: false,
  menuOptions: () => [],
  deptOptions: () => [],
  checkedMenuOptions: () => [],
  operation: 'add'
})

// 表单引用
const ruleFormRef = ref<FormInstance>()
// 菜单引用
const menuRef = ref()
// 部门引用
const deptRef = ref()
// 菜单是否展开
const menuExpand = ref(false)
// 菜单是否全选
const menuNodeAll = ref(false)
// 菜单检索值
const menuFilterText = ref('')
// 展示表单
const showFormInfo = ref<any>()

const editDialogVisible = computed({
  get() {
    return defProps.visible
  },
  set(val) {
    emits('update:visible', val)
  }
})

const defaultProps = {
  children: "children",
  label: "label"
}

// 表单校验规则
const formRules = reactive<any>({})
// 是否加载
const editDialogLoading = computed({
  get() {
    return defProps.loading
  },
  set(val) {
    emits("update:loading", val)
  }
})

// 触发父组件事件
const emits = defineEmits<{
  (e: 'update:visible', isVisiable: boolean): void,
  (e: 'update:loading', isLoading: boolean): void,
  (e: 'handleClose'): void
  (e: 'submit', form: any): void
}>()

// 提交事件
const submitEditForm = () => {
  ruleFormRef?.value?.validate((valid, fields) => {
    if (valid) {
      emits("submit", defProps.editForm)
    } else {
      console.log('error submit!', fields)
    }
  })
}

// 关闭前回调
const handleClose = () => {
  // 重置表单
  ruleFormRef?.value?.resetFields();
  emits('handleClose')
}

// 表单校验方法
const validateFormFunction = (rule: any, value: any, callback: any) => {
  for (let i in defProps.formInfo) {
    let item = defProps.formInfo[i];
    if (item.prop == rule.field) {
      if (item.validateFunction) { // 如果是自定义校验
        item.validateFunction(rule, value, callback, defProps.editForm);
      }
      break;
    }
  }
}

// 根据表单信息数据，构建表单校验数据
const buildFormRules = () => {
  for (let i in showFormInfo.value) {
    let item = showFormInfo.value[i];
    formRules[item.prop] = [];
    if (item.rules && item.rules.length > 0) {
      formRules[item.prop] = item.rules;
    }
    if (item.validateFunction) { // 如果有校验方法，说要有自定义校验规则
      const validateItem = {
        validator: validateFormFunction,
        trigger: item.validateTrigger
      }
      formRules[item.prop].push(validateItem)
    }
  }
}

// 树权限（展开/折叠）
const handleCheckedTreeExpand = (value, type) => {
  if (type == 'menu') {
    let treeList = defProps.menuOptions;
    for (let i = 0; i < treeList.length; i++) {
      menuRef.value[0]!.store.nodesMap[treeList[i].id].expanded = value;
    }
  } else if (type == 'dept') {
    let treeList = defProps.deptOptions;
    for (let i = 0; i < treeList.length; i++) {
      deptRef.value[0]!.store.nodesMap[treeList[i].id].expanded = value;
    }
  }
}

// 树权限（全选/全不选）
const handleCheckedTreeNodeAll = (value, type) => {
  if (type == 'menu') {
    menuRef.value[0]!.setCheckedNodes(value ? defProps.menuOptions : []);
  } else if (type == 'dept') {
    deptRef.value[0]!.setCheckedNodes(value ? defProps.deptOptions : []);
  }
}

// 树权限（父子联动）
const handleCheckedTreeConnect = (value, type) => {
  if (type == 'menu') {
    defProps.editForm.menuCheckStrictly = value ? true : false;
  } else if (type == 'dept') {
    defProps.editForm.deptCheckStrictly = value ? true : false;
  }
}

// 搜索菜单
const handleMenuFilter = (value, data) => {
  if (!value) return true
  return data.label.includes(value)
}

watch(menuFilterText, (val) => {
  menuRef.value[0].filter(val)
})

watch(
  () => defProps.checkedMenuOptions,
  (newValue, oldValue) => {
    defProps.checkedMenuOptions.forEach((v) => {
      nextTick(() => {
        menuRef.value[0].setChecked(v, true, false)
      })
    })
  },
  { deep: true }
)

watch(
  () => defProps.operation,
  (value) => {
    showFormInfo.value = defProps.formInfo.filter(item => (!item.operation || item.operation === 'all' || item.operation === defProps.operation))
  }
)

buildFormRules()
</script>

<style lang="scss" scoped>
@include b(common-dialog) {
  :deep(.el-dialog) {

    // 弹出窗口的头部
    .el-dialog__header {
      padding: 0px 35px;
      height: 80px;
      line-height: 80px;
      font-size: 20px;
      font-weight: 700;
      color: #2D2D2D;

      @include useTheme {
        border-bottom: 1px solid getVar('borderColor');
      }

      .el-dialog__headerbtn {
        top: 15px;
        right: 10px;
      }
    }

    // 弹窗窗口的内容部分
    .el-dialog__body {
      padding: 15px;

      @include b(common-dialog-container) {
        max-height: v-bind(dialogHeight);
        overflow: auto;
        padding: 15px;

        .el-row {

          @include useTheme {
            border-left: 1px solid getVar('editDialogBorderColor');
          }

          .el-col {
            min-height: 56px;

            &:nth-child(1) {
              @include useTheme {
                border-top: 1px solid getVar('editDialogBorderColor');
              }
            }

            &:nth-child(2) {
              @include useTheme {
                border-top: 1px solid getVar('editDialogBorderColor');
              }
            }

            .el-form-item {
              margin: 0;
              height: 100%;
              align-items: center;

              @include useTheme {
                border-right: 1px solid getVar('editDialogBorderColor');
                border-bottom: 1px solid getVar('editDialogBorderColor');
              }

              .el-form-item__label {
                font-weight: 700;
                display: inline-flex;
                align-items: center;
                justify-content: center;
                flex-wrap: nowrap;
                height: 100%;

                @include useTheme {
                  border-right: 1px solid getVar('editDialogBorderColor');
                  background-color: getVar('editDialogLabelBgColor');
                }
              }

              .el-form-item__content {
                padding: 5px;

                @include b(menu-permission-box) {
                  padding-left: 10px;
                  width: 100%;
                  text-align: left;

                  .el-tree {
                    max-height: 200px;
                    overflow: auto;
                  }
                }
              }



              .el-form-item__error {
                z-index: 10;
              }

              .el-input {
                border: none;
                box-shadow: none;

                .el-input__wrapper {
                  border: none;
                  box-shadow: none;
                  min-height: 54px;
                }
              }

              .el-select {
                width: 100%;
              }

              .el-textarea__inner {
                box-shadow: none;
              }
            }
          }
        }
      }


      // 底部按钮
      .dialog-footer {
        padding-top: 20px;
        display: flex;
        justify-content: flex-end;
      }
    }
  }
}
</style>